#include "GameConfigManager.h"

#include <fstream>

#include "utilities/Conversion.h"

GameConfigManager::GameConfigManager()
{
	soundVolume = 100 * 0.01;
	musicVolume = 100 * 0.01;
	particlesEnabled = true;

	jumpKey      = "B";
	walkLeftKey  = "Left";
	walkRightKey = "Right";
	crouchKey    = "Down";

	selectionUpKey    = "Up";
	selectionLeftKey  = "Left";
	selectionRightKey = "Right";
	selectionDownKey  = "Down";

	runKey = "x";

	#ifndef GP2X_WIZ
		pauseKey = "M";
	#else
		pauseKey = "Menu";
	#endif

	lookUpKey    = "Up";
	lookLeftKey  = "Left";
	lookRightKey = "Right";
	lookDownKey  = "Down";
}

bool GameConfigManager::LoadFromFile( const std::string& filename )
{
	std::fstream file( filename.c_str(), std::fstream::in );

	if ( !file.is_open() or !file.good() )
	{
		// Something went wrong.
		return false;
	}

	while ( !file.eof() )
	{
		if ( file.fail() )
		{
			// Something went wrong.
			return false;
		}

		std::string line = "";

		std::getline( file, line );

		if ( line == "" )
		{
			// Blank line, keep going.
			continue;
		}

		if ( line.find( "=" ) == std::string::npos )
		{
			// Malformed line, keep going.
			continue;
		}

		std::string option = line.substr( 0, line.find( "=" ) );
		std::string key    = line.substr( line.find( "=" ) + 1 );

		if ( !IsOptionValid( option ) )
		{
			// Something was invalid, keep going.
			continue;
		}
		if ( option != "Sound" and option != "Music" and option != "Particles" and !IsKeyValid( key ) )
		{
			// Something was invalid, keep going.
			continue;
		}

		// Switch won't work with a string.
		if ( option == "Sound" )
		{
			soundVolume = util::ConvertFromStringTo< int >( key ) * 0.01;
		}
		else if ( option == "Music" )
		{
			musicVolume = util::ConvertFromStringTo< int >( key ) * 0.01;
		}
		else if ( option == "Particles" )
		{
			if ( key == "false" )
			{
				particlesEnabled = false;
			}
			else
			{
				particlesEnabled = true;
			}
		}
		else if ( option == "Jump" )
		{
			jumpKey = key;
		}
		else if ( option == "WalkLeft" )
		{
			walkLeftKey = key;
		}
		else if ( option == "WalkRight" )
		{
			walkRightKey = key;
		}

		else if ( option == "Crouch" )
		{
			crouchKey = key;
		}
		else if ( option == "SelectionUp" )
		{
			selectionUpKey = key;
		}

		else if ( option == "SelectionLeft" )
		{
			selectionLeftKey = key;
		}
		else if ( option == "SelectionRight" )
		{
			selectionRightKey = key;
		}
		else if ( option == "SelectionDown" )
		{
			selectionDownKey = key;
		}
		else if ( option == "Run" )
		{
			runKey = key;
		}
		else if ( option == "Pause" )
		{
			pauseKey = key;
		}
		else if ( option == "LookUp" )
		{
			lookUpKey = key;
		}
		else if ( option == "LookLeft" )
		{
			lookLeftKey = key;
		}
		else if ( option == "LookRight" )
		{
			lookRightKey = key;
		}
		else if ( option == "LookDown" )
		{
			lookDownKey = key;
		}
	}

	return true;
}

bool GameConfigManager::SaveToFile( const std::string& filename ) const
{
	std::fstream file( filename.c_str(), std::fstream::out | std::fstream::trunc );

	if ( !file.is_open() or !file.good() )
	{
		return false;
	}

	file << "Sound" << "=" << ( soundVolume * 100 ) << std::endl;
	file << "Music" << "=" << ( musicVolume * 100 ) << std::endl;

	if ( particlesEnabled )
	{
		file << "Particles" << "=" << "true" << std::endl;
	}
	else
	{
		file << "Particles" << "=" << "false" << std::endl;
	}

	file << std::endl;

	file << "Jump" << "=" << jumpKey << std::endl;
	file << "WalkLeft" << "=" << walkLeftKey << std::endl;
	file << "WalkRight" << "=" << walkRightKey << std::endl;
	file << "Crouch" << "=" << crouchKey << std::endl;

	file << std::endl;

	file << "SelectionUp" << "=" << selectionUpKey << std::endl;
	file << "SelectionLeft" << "=" << selectionLeftKey << std::endl;
	file << "SelectionRight" << "=" << selectionRightKey << std::endl;
	file << "SelectionDown" << "=" << selectionDownKey << std::endl;

	file << std::endl;

	file << "Run" << "=" << runKey << std::endl;

	file << std::endl;

	file << "Pause" << "=" << pauseKey << std::endl;

	file << std::endl;

	file << "LookUp" << "=" << lookUpKey << std::endl;
	file << "LookLeft" << "=" << lookLeftKey << std::endl;
	file << "LookRight" << "=" << lookRightKey << std::endl;
	file << "LookDown" << "=" << lookDownKey << std::endl;

	file.close();

	return true;
}

float GameConfigManager::GetSoundVolume() const
{
	return soundVolume * 100;
}

void GameConfigManager::SetSoundVolume( float theVolume )
{
	soundVolume = theVolume * 0.01;
}

float GameConfigManager::GetMusicVolume() const
{
	return musicVolume * 100;
}

void GameConfigManager::SetMusicVolume( float theVolume )
{
	musicVolume = theVolume * 0.01;
}

bool GameConfigManager::GetParticlesEnabled() const
{
	return particlesEnabled;
}

void GameConfigManager::SetParticlesEnabled( bool theParticlesEnabled )
{
	particlesEnabled = theParticlesEnabled;
}

std::string GameConfigManager::GetJumpKey() const
{
	return jumpKey;
}

void GameConfigManager::SetJumpKey( const std::string& theKey )
{
	jumpKey = theKey;
}

std::string GameConfigManager::GetWalkLeftKey() const
{
	return walkLeftKey;
}

void GameConfigManager::SetWalkLeftKey( const std::string& theKey )
{
	walkLeftKey = theKey;
}

std::string GameConfigManager::GetWalkRightKey() const
{
	return walkRightKey;
}

void GameConfigManager::SetWalkRightKey( const std::string& theKey )
{
	walkRightKey = theKey;
}

std::string GameConfigManager::GetCrouchKey() const
{
	return crouchKey;
}

void GameConfigManager::SetCrouchKey( const std::string& theKey )
{
	crouchKey = theKey;
}

std::string GameConfigManager::GetSelectionUpKey() const
{
	return selectionUpKey;
}

void GameConfigManager::SetSelectionUpKey( const std::string& theKey )
{
	selectionUpKey = theKey;
}

std::string GameConfigManager::GetSelectionLeftKey() const
{
	return selectionLeftKey;
}

void GameConfigManager::SetSelectionLeftKey( const std::string& theKey )
{
	selectionLeftKey = theKey;
}

std::string GameConfigManager::GetSelectionRightKey() const
{
	return selectionRightKey;
}

void GameConfigManager::SetSelectionRightKey( const std::string& theKey )
{
	selectionRightKey = theKey;
}

std::string GameConfigManager::GetSelectionDownKey() const
{
	return selectionDownKey;
}

void GameConfigManager::SetSelectionDownKey( const std::string& theKey )
{
	selectionDownKey = theKey;
}

std::string GameConfigManager::GetRunKey() const
{
	return runKey;
}

void GameConfigManager::SetRunKey( const std::string& theKey )
{
	runKey = theKey;
}

std::string GameConfigManager::GetPauseKey() const
{
	return pauseKey;
}

void GameConfigManager::SetPauseKey( const std::string& theKey )
{
	pauseKey = theKey;
}

std::string GameConfigManager::GetLookUpKey() const
{
	return lookUpKey;
}

void GameConfigManager::SetLookUpKey( const std::string& theKey )
{
	lookUpKey = theKey;
}

std::string GameConfigManager::GetLookLeftKey() const
{
	return lookLeftKey;
}

void GameConfigManager::SetLookLeftKey( const std::string& theKey )
{
	lookLeftKey = theKey;
}

std::string GameConfigManager::GetLookRightKey() const
{
	return lookRightKey;
}

void GameConfigManager::SetLookRightKey( const std::string& theKey )
{
	lookRightKey = theKey;
}

std::string GameConfigManager::GetLookDownKey() const
{
	return lookDownKey;
}

void GameConfigManager::SetLookDownKey( const std::string& theKey )
{
	lookDownKey = theKey;
}

InputController GameConfigManager::GetInputController() const
{
	InputController input;

	input.jumpKey = ConvertToInputController( jumpKey );
	input.walkLeftKey = ConvertToInputController( walkLeftKey );
	input.walkRightKey = ConvertToInputController( walkRightKey );
	input.crouchKey = ConvertToInputController( crouchKey );

	input.selectionUpKey = ConvertToInputController( selectionUpKey );
	input.selectionLeftKey = ConvertToInputController( selectionLeftKey );
	input.selectionRightKey = ConvertToInputController( selectionRightKey );
	input.selectionDownKey = ConvertToInputController( selectionDownKey );

	input.runKey = ConvertToInputController( runKey );

	input.pauseKey = ConvertToInputController( pauseKey );

	input.lookUpKey = ConvertToInputController( lookUpKey );
	input.lookLeftKey = ConvertToInputController( lookLeftKey );
	input.lookRightKey = ConvertToInputController( lookRightKey );
	input.lookDownKey = ConvertToInputController( lookDownKey );

	return InputController();
}

bool GameConfigManager::IsOptionValid( const std::string& optionName ) const
{
	if ( optionName == "Sound" or optionName == "Music" or optionName == "Particles" or
	     optionName == "Jump" or optionName == "WalkLeft" or optionName == "WalkRight" or
	     optionName == "Crouch" or optionName == "SelectionUp" or optionName == "SelectionLeft" or
	     optionName == "SelectionRight" or optionName == "SelectionDown" or optionName == "Run" or
	     optionName == "Pause" or optionName == "LookUp" or optionName == "LookLeft" or
	     optionName == "LookRight" or optionName == "LookDown" )
	{
		return true;
	}

	return false;
}

bool GameConfigManager::IsKeyValid( const std::string& keyName ) const
{
	if ( keyName == "Up" or keyName == "Left" or keyName == "Right" or
	     keyName == "Down" or keyName == "Y" or keyName == "A" or
	     keyName == "B" or keyName == "X" or keyName == "M" or
	     keyName == "Menu" or keyName == "S" or keyName == "Select" or
	     keyName == "L" or keyName == "R" )
	{
		return true;
	}

	return false;
}

gdn::Key::Code GameConfigManager::ConvertToInputController( const std::string& keyName ) const
{
	if ( keyName == "Up" )
	{
		return gdn::Key::UpArrow;
	}
	else if ( keyName == "Left" )
	{
		return gdn::Key::LeftArrow;
	}
	else if ( keyName == "Right" )
	{
		return gdn::Key::RightArrow;
	}
	else if ( keyName == "Down" )
	{
		return gdn::Key::DownArrow;
	}
	else if ( keyName == "Y" )
	{
		return gdn::Key::Y;
	}
	else if ( keyName == "A" )
	{
		return gdn::Key::A;
	}
	else if ( keyName == "B" )
	{
		return gdn::Key::B;
	}
	else if ( keyName == "X" )
	{
		return gdn::Key::X;
	}
	else if ( keyName == "M" or keyName == "Menu" )
	{
		return gdn::Key::M;
	}
	else if ( keyName == "S" or keyName == "Select" )
	{
		return gdn::Key::S;
	}
	else if ( keyName == "L" )
	{
		return gdn::Key::L;
	}
	else if ( keyName == "R" )
	{
		return gdn::Key::R;
	}

	return gdn::Key::Count;
}
